﻿using Framework.Config;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Framework.Infrastructure;
using Framework.Command;
using Framework.Event;

namespace Framework.Bus.MsmqServiceBus
{
    public static class MessageHandlerFactory
    {
        public static List<TaskWorker> MessageHandlers = new List<TaskWorker>();
        public static void BuildMessageHandlers()
        {
            var endpointsMappings = ConfigurationReader.Instance
                               .GetConfigurationSection<FrameworkConfigurationSection>()
                               .MessageEndpointMappings;

            var commandDispatcher = AsyncCommandDispatcher;
            var eventDispatcher = AsyncEventDispatcher;

            foreach (EndpointElement endpointElement in endpointsMappings)
            {
                IMessageDispatcher messageDispatcher = null;
                if (typeof(ICommand).IsAssignableFrom(Type.GetType(endpointElement.MessageType)))
                {
                    messageDispatcher = commandDispatcher;
                }
                else if (typeof(IDomainEvent).IsAssignableFrom(Type.GetType(endpointElement.MessageType)))
                {
                    messageDispatcher = eventDispatcher;
                }
                if (messageDispatcher != null)
                {
                    MessageHandlers.Add(new MessageHandler(messageDispatcher, endpointElement).Start());
                }
            }
        }

        static IMessageDispatcher _AsyncCommandDispatcher;
        public static IMessageDispatcher AsyncCommandDispatcher
        {
            get
            {
                try
                {
                    if (_AsyncCommandDispatcher == null)
                    {
                        Configuration.Instance.CommandDispatcherBuild()
                                              .SyncEventDispatcherBuild()
                                              .AggregateRootEventHandlerBuild();
                        _AsyncCommandDispatcher = IoCFactory.Resolve<IMessageDispatcher>(Constants.Configuration.CommandDispatcher);
                    }
                    return _AsyncCommandDispatcher;
                }
                catch (System.Exception)
                {
                    return null;
                }
            }
        }


        static IMessageDispatcher _AsyncEventDispatcher;
        public static IMessageDispatcher AsyncEventDispatcher
        {
            get
            {
                try
                {
                    if (_AsyncEventDispatcher == null)
                    {
                        Configuration.Instance.AsyncEventDispatcherBuild();
                        _AsyncEventDispatcher = IoCFactory.Resolve<IMessageDispatcher>(Constants.Configuration.AsyncEventDispatcher);
                    }
                    return _AsyncEventDispatcher;
                }
                catch (System.Exception)
                {
                    return null;
                }
              
            }
        }


        public static void Start()
        {
            MessageHandlers.ForEach(messageHandler => { messageHandler.Start(); });
        }

        public static void Terminate(int millionSecondsTimeout = 0)
        {
            MessageHandlers.ForEach(messageHandler => { messageHandler.Stop(true); });
            MessageHandlers.ForEach(messageHandler => { messageHandler.Wait(millionSecondsTimeout); });
        }
    }
}
